package math.geom3d;

import math.base.Coord3d;
import math.base.Dir3d;
import math.base.Point3d;
import math.base.Vector3d;
import math.geomUtils.CurveType;

/**
 * @author Saga
 *
 */
public class Line3d extends Curve3d {
    public Line3d() {
        this.origin = new Point3d();
        this.direct = new Dir3d();
    }

    public Line3d(final Point3d _origin, final Dir3d _direct) {
        this.origin = _origin;
        this.direct = _direct;
    }

    @Override
    public final CurveType getCurveType() {
        return CurveType.LINE;
    }

    @Override
    public final void reverse() {
        this.direct.reverse();
    }

    @Override
    public final Curve3d reversed() {
        return new Line3d(this.origin, this.direct.reversed());
    }

    @Override
    public final boolean isPeriodic() {
        return false;
    }

    @Override
    public final double getPeriod() {
        throw new ArithmeticException("");
    }

    @Override
    public final double getFirstParameter() {
        return Double.NEGATIVE_INFINITY;
    }

    @Override
    public final double getLastParameter() {
        return Double.POSITIVE_INFINITY;
    }

    public final void setOrigin(final Point3d _origin) {
        this.origin = _origin;
    }

    public final Point3d getOrigin() {
        return this.origin;
    }

    public final void setDirect(final Dir3d _direct) {
        this.direct = _direct;
    }

    public final Dir3d getDirect() {
        return this.direct;
    }

    @Override
    public final Point3d calcValue(final double _param) {
        return this.origin.added(this.direct.multiplied(_param));
    }

    @Override
    public final Vector3d calcDerivative(final double _param) {
        return new Vector3d(this.direct);
    }

    @Override
    public final Vector3d calcDerivativeN(final double _param, final int _order) {
        if (_order < 1) {
            throw new ArithmeticException("");
        } else if (_order == 1) {
            return new Vector3d(this.direct);
        } else {
            return new Vector3d();
        }
    }

    @Override
    public final void calcValueAndDerivative1(final double _param, final Point3d _pt,
            final Vector3d _der1) {
        _pt.setCoord(this.origin.getCoord().added(this.direct.getCoord().multiplied(_param)));
        _der1.setCoord(this.direct.getCoord());
    }

    @Override
    public final void calcValueAndDerivative2(final double _param, final Point3d _pt,
            final Vector3d _der1, final Vector3d _der2) {
        _pt.setCoord(this.origin.getCoord().added(this.direct.getCoord().multiplied(_param)));
        _der1.setCoord(this.direct.getCoord());
        _der2.setCoord(new Coord3d(0.0, 0.0, 0.0));
    }

    @Override
    public final void calcValueAndDerivative3(final double _param, final Point3d _pt,
            final Vector3d _der1, final Vector3d _der2, final Vector3d _der3) {
        _pt.setCoord(this.origin.getCoord().added(this.direct.getCoord().multiplied(_param)));
        _der1.setCoord(this.direct.getCoord());
        _der2.setCoord(new Coord3d(0.0, 0.0, 0.0));
        _der3.setCoord(new Coord3d(0.0, 0.0, 0.0));
    }

    private Point3d origin;
    private Dir3d direct;
}
